package priv.conceit.study.leetcode.simple.official;

import java.util.concurrent.CountDownLatch;

/**
 * 编号：1114
 * 线程按需打印
 *
 * @description: <a href="https://leetcode-cn.com/problems/print-in-order/">
 * @return:
 * @author: conceit
 * @date: 2019/11/1 15:00
 */
public class PrintInOrder {
	CountDownLatch countDownLatchA;
	CountDownLatch countDownLatchB;

	/**
	 * CountDownLatch提供的机制是多个（具体数量等于初始化CountDownLatch时count的值）线程都达到了
	 * 预期状态或者完成了预期工作时触发事件，
	 * 其他线程可以等待这个事件来触发自己后续的工作。
	 * 等待的线程可以是多个，即CountDownLatch可以唤醒多个等待的线程。
	 * 到达自己预期状态的线程会调用CountDownLatch的countDown方法，
	 * 而等待的线程会调用CountDownLatch的await方法
	 * <p>
	 * 思路
	 * 线程a 线程b 使用一个闭锁
	 * b中等待闭锁释放
	 * a先占锁，执行完毕释放
	 * b在执行
	 * <p>
	 * 线程b 线程c 也使用同一个闭锁
	 * 重复以上操作
	 *
	 * @param args
	 */
	public static void main(String[] args) throws InterruptedException {
		PrintInOrder printInOrder = new PrintInOrder();
//		new Thread(()-> System.out.println("second"));
//		new Thread(()-> System.out.println("third"));
//		new Thread(()-> System.out.println("first"));
		Runnable runnableA = () -> System.out.println("first");
		Runnable runnableB = () -> System.out.println("second");
		Runnable runnableC = () -> System.out.println("third");

		//声名线程
		new Thread(() -> printInOrder.first(runnableA)).start();
		new Thread(() -> printInOrder.second(runnableB)).start();
		new Thread(() -> printInOrder.third(runnableC)).start();
	}


	public PrintInOrder() {
		countDownLatchA = new CountDownLatch(1);
		countDownLatchB = new CountDownLatch(1);
	}

	public void first(Runnable printFirst) {
		// printFirst.run() outputs "first". Do not change or remove this line.
		printFirst.run();

		//直接执行并释放
		countDownLatchA.countDown();
	}

	public void second(Runnable printSecond) {
		//等待闭锁A释放
		try {
			countDownLatchA.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		// printSecond.run() outputs "second". Do not change or remove this line.
		printSecond.run();
		countDownLatchB.countDown();
	}

	public void third(Runnable printThird) {
		//等待闭锁B释放
		try {
			countDownLatchB.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		// printThird.run() outputs "third". Do not change or remove this line.
		printThird.run();
	}


}
